﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Collections;
using System.Threading;
using Serie_Counter.DataLayer;
using Serie_Counter.General;

namespace Serie_Counter.BusinissLayer
{
    /// <summary>
    /// manager class
    /// </summary>
    public class BL_Manager
    {
        private IO_Series ioSeries;
        private SerieCollection serieCollection;
        private List<string> oldCoverPaths;
        private const string OLD_COVER_PATH = "oldCover.dat";
        //file moving
        private BL_FileMoving fileMoving;

        public SerieCollection SerieCollection
        {
            get
            {
                return serieCollection;
            }
        }

        /// <summary>
        /// standaard constructor
        /// </summary>
        public BL_Manager()
        {
            ioSeries = new IO_Series();
            serieCollection = new SerieCollection();
            fileMoving = new BL_FileMoving(this.getSettings().CheckInterval,this);
            oldCoverPaths = new List<string>();

            readDefaultFile();
            serieCollection.updateAirdates();
            removeOldCovers();

            //set settings events
            //set settings events
            getSettings().selectedMoveOptionChanged += new SelectedMoveOptionChanged(checkAutoMoveOptionChanged);
            
        }

        ~BL_Manager()
        {
            if(oldCoverPaths.Count != 0)
            {
                IO_Covers.saveOldCoversPathsFile(OLD_COVER_PATH, oldCoverPaths);
            }
        }

        /// <summary>
        /// contructor
        /// </summary>
        /// <param name="File">series filepath</param>
        public BL_Manager(string File)
        {
            ioSeries = new IO_Series();
            serieCollection = ioSeries.Read(File);
        }

        #region filemoving

        public void startFilemovingTimer()
        {
            fileMoving.start();
        }

        public void pauseFilemovingTimer()
        {
            fileMoving.pause();
        }

        private void checkAutoMoveOptionChanged(AutoMoveOption selectedOption, int interval)
        {
            switch (selectedOption)
            {
                //start thread for time moving
                case AutoMoveOption.Time:
                    fileMoving.TimerInterval = interval;
                    fileMoving.start();
                    break;
                //stop thread if IS alive.
                case AutoMoveOption.Startup:
                case AutoMoveOption.Manual:
                    fileMoving.pause();
                    break;
                default: break;
            }
        }

        public void checkFiles()
        {
            fileMoving.checkFiles();
        }

        #endregion

        #region Io functions

        /// <summary>
        /// export current series to txt file
        /// </summary>
        /// <param name="file">file path</param>
        public void Export(string file)
        {
            ioSeries.Write(file, serieCollection);
        }

        /// <summary>
        /// import series file
        /// </summary>
        /// <param name="file">file path</param>
        public void import(string file)
        {
            serieCollection = ioSeries.Read(file);
        }

        /// <summary>
        /// read standaard saved file (at root)
        /// </summary>
        public void readDefaultFile()
        {
            serieCollection = ioSeries.ReadDefault();
        }

        /// <summary>
        /// save content at default serieList path
        /// </summary>
        public void saveCurrentContent()
        {
            ioSeries.WriteDefault(serieCollection);
        }


        #region Setting actions

        /// <summary>
        /// get The settings
        /// Events in the settings need to be re assigned when first deSerializing the setting
        /// </summary>
        /// <returns>Settings</returns>
        public Settings getSettings()
        {
            return IO_Settings.GetSettings();
        }

        public void setSettings(Settings settings)
        {
            IO_Settings.SetSettings(settings);
            IO_Settings.writeSettings();
        }

        /// <summary>
        /// Get default save path of the serie data from the settings.
        /// </summary>
        /// <returns></returns>
        public string getDefaultSavePath()
        {
            return IO_Settings.GetSettings().SerieListSavePath;
        }

        public void setDefaultSavePath(string defaultSavePath)
        {
            IO_Settings.GetSettings().SerieListSavePath = defaultSavePath;
            IO_Settings.writeSettings();
        }

        public bool getAutoStart()
        {
            return IO_Settings.GetSettings().AutoStart;
        }

        public void setAutostart(bool autoStart)
        {
            IO_Settings.GetSettings().AutoStart = autoStart;
            IO_Settings.writeSettings();
        }

        public bool getEnableReminder()
        {
            return IO_Settings.GetSettings().EnableRember;
        }

        public void setEnableReminder(bool enableRember)
        {
            IO_Settings.GetSettings().EnableRember = enableRember;
            IO_Settings.writeSettings();
        }

        public bool getCloseWithMainForm()
        {
            return IO_Settings.GetSettings().CloseWithMainForm;
        }

        #endregion

        

        #endregion

        #region Actions

        /// <summary>
        /// add new serie
        /// </summary>
        /// <param name="titel">serie title</param>
        /// <param name="season">serie season</param>
        /// <param name="episode">serie episode</param>
        /// <param name="nextAirDate">serie nextAirDate</param>
        //todo: rewrite more efficient: use serie object instead of all parameters of the serie object
        public void addSerie(string titel, int season, int episode, DateTime nextAirDate, int frequency, int curSeason, int curEpisode, MemoryStream coverStream, SelectedCollection collection, string moveDestPath)
        {
            if(coverStream == null)
            {
                serieCollection.addSerie(new Serie(titel,season,episode,nextAirDate,frequency,null,curSeason,curEpisode,moveDestPath),SelectedCollection.Active);
            }
            else
            {
                string coverPath = GeneralVars.DEFAULT_COVER_FOLDER_PATH + new string(titel.ToCharArray().Where(c => !char.IsPunctuation(c)).ToArray()) + ".jpg";

                //@todo might need to check if it alwayse is an JPG
                IO_Covers.saveCover(coverPath, coverStream); 
                serieCollection.addSerie(new Serie(titel,season,episode,nextAirDate,frequency,coverPath,curSeason,curEpisode,moveDestPath),collection);
            }
            
        }
        

        /// <summary>
        /// remove serie 
        /// </summary>
        /// <param name="titel">serie title</param>
        public void removeSerie(string titel, SelectedCollection collection)
        {
            if(serieCollection.removeSerie(titel,collection))
            {
                try
                {
                    IO_Covers.removeCover("Covers/" + new string(titel.ToCharArray().Where(c => !char.IsPunctuation(c)).ToArray()) + ".jpg");
                }
                catch (Exception e)
                {
                    Debug.WriteLine(e.Message);
                }
            }
        }

        /// <summary>
        /// update serie from active serie list
        /// </summary>
        /// <param name="uSerie">new serie object</param>
        public void updateSerie(Serie uSerie, SelectedCollection collection, string oldTitle = null, MemoryStream coverStream = null)
        {
            if(coverStream != null)
            {
                string oldPath = uSerie.CoverPath;
                string coverPath = GeneralVars.DEFAULT_COVER_FOLDER_PATH + new string(uSerie.Titel.ToCharArray().Where(c => !char.IsPunctuation(c)).ToArray()) + ".jpg";
                if (File.Exists(coverPath))
                {
                    oldPath = coverPath;
                    Random random = new Random();
                    coverPath = GeneralVars.DEFAULT_COVER_FOLDER_PATH + new string(uSerie.Titel.ToCharArray().Where(c => !char.IsPunctuation(c)).ToArray()) + random.Next(0,10000)+ ".jpg";
                }
                IO_Covers.saveCover(coverPath, coverStream);
               
                oldCoverPaths.Add(oldPath); //add old cover path to array, they will be removed at next startup.
                uSerie.CoverPath = coverPath;
            }
            serieCollection.updateSerie(uSerie,oldTitle,collection);
        }

        /// <summary>
        /// gets the remember message
        /// </summary>
        /// <returns></returns>
        public string getRememberMessage()
        {
            
            List<Serie> temp = serieCollection.getAiredSeries(IO_Settings.GetSettings().WarningDelay);
            StringBuilder sb = new StringBuilder();

            if(temp.Count != 0)
            {
                foreach (Serie serie in temp)
                {
                    sb.AppendLine(serie.Titel + ":   Season: " + serie.CurSeason + "  Episode: " + serie.CurEpisode);
                }

                return sb.ToString();
            }
            else
            {
                return null;
            }
        }

        #endregion
        
        
        #region general

        public void moveSerieActiveToArchived(Serie serie)
        {
            serieCollection.moveSerieActiveToArchived(serie);
        }

        public void moveSerieArchivedToActive(Serie serie)
        {
            serieCollection.moveSerieArchivedToActive(serie);
        }

        public MemoryStream getCoverPic(string title)
        {
            string coverUrl = IO_IMDB.getPic(title);

            if (!coverUrl.Equals("NULL"))
            {
                return IO_IMDB.DownloadCover(coverUrl);
            }
            else
            {
                return null;
            }
        }

        public void removeOldCovers()
        {
            oldCoverPaths = IO_Covers.getOldCoversPathsFile(OLD_COVER_PATH);

            if(oldCoverPaths.Count != 0)
            {
                for (int i = oldCoverPaths.Count-1; i >= 0; i--)
                {
                    if (File.Exists(oldCoverPaths[i]))
                    {
                        File.Delete(oldCoverPaths[i]);
                        oldCoverPaths.RemoveAt(i);
                    }
                }
            }
        }

        public List<string[]> getMoveAbleSeries()
        {
            List<string[]> moveAbleSeries = new List<string[]>();

            foreach (Serie serie in serieCollection.ActiveSeries)
            {
                 if(Directory.Exists(serie.TransferPath))
                 {
                     moveAbleSeries.Add(new string[2]{serie.Titel,serie.TransferPath});
                 }
            }

            return moveAbleSeries;
        }

        #endregion
    }
}
